package com.br.framework.util.file;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.swing.ImageIcon;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class ImageUtil {

	private static Log logger = LogFactory.getLog(ImageUtil.class);
	public static final int SAME = -1; // width 혹은 height 변경시 나머지 길이는 변하지 않음
	public static final int RATIO = 0; // width 혹은 height 변경시 나머지 길이도 같은 비율로 변함

	 /**
	 * 이미지 사이즈 변경..
	 * @param src
	 * @param dest
	 * @param width
	 * @param height
	 * @throws IOException
	 * @date 2009. 5. 25
	 */
	public static void resize(File src, File dest, int width, int height) throws IOException {
		Image srcImg = null;
		String suffix = src.getName().substring(src.getName().lastIndexOf('.')+1).toLowerCase();
		if (suffix.equals("bmp") || suffix.equals("png") || suffix.equals("gif")) {
        	srcImg = ImageIO.read(src);
		} else {
			// BMP가 아닌 경우 ImageIcon을 활용해서 Image 생성
            // 이렇게 하는 이유는 getScaledInstance를 통해 구한 이미지를
            // PixelGrabber.grabPixels로 리사이즈 할때
			// 빠르게 처리하기 위함이다.
            srcImg = new ImageIcon(src.getPath()).getImage();
        }
		int srcWidth = srcImg.getWidth(null);
		int srcHeight = srcImg.getHeight(null);

		int destWidth = -1, destHeight = -1;

		if (width == SAME) {
			destWidth = srcWidth;
		} else if (width > 0) {
        	destWidth = width;
		}

		if (height == SAME) {
        	destHeight = srcHeight;
		} else if (height > 0) {
			destHeight = height;
		}

		if (width == RATIO && height == RATIO) {
			destWidth = srcWidth;
			destHeight = srcHeight;
		} else if (width == RATIO) {
			double ratio = ((double)destHeight) / ((double)srcHeight);
			destWidth = (int)(srcWidth * ratio);
		} else if (height == RATIO) {
			double ratio = ((double)destWidth) / ((double)srcWidth);
			destHeight = (int)(srcHeight * ratio);
		}
		Image imgTarget = srcImg.getScaledInstance(destWidth, destHeight, Image.SCALE_SMOOTH);
		int pixels[] = new int[destWidth * destHeight];
		PixelGrabber pg = new PixelGrabber(imgTarget, 0, 0, destWidth, destHeight, pixels, 0, destWidth);
		try {
        	pg.grabPixels();
		} catch (InterruptedException e) {
			throw new IOException(e.getMessage());
		}
		BufferedImage destImg = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
		destImg.setRGB(0, 0, destWidth, destHeight, pixels, 0, destWidth);
		ImageIO.write(destImg, "png", dest);
	}

    /**
     * 이미지 크기반환
     * @param src
     * @return int[0]=넒이 int[1]=높이
     * @throws IOException
     * @date 2009. 5. 25
     */
    public static int[] getWidth(File src) throws IOException {
        BufferedImage srcImg = ImageIO.read(src); // Image를 읽어들임
        int srcWidth = srcImg.getWidth();
        int srcHeight = srcImg.getHeight();
        int rst[]=new int[2];
        rst[0]=srcWidth;
        rst[1]=srcHeight;
        return rst;
    }

	/**
	 * <strong>title</strong> : CreateQRCode  <BR/>
	 * <strong>description</strong> : QR코드생성하기 <BR/>
	 * <strong>date</strong> : 2010. 12. 30.
	 * @param request
	 * @param id
	 * @param scale
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	/*public static File CreateQRCode(HttpServletRequest request,String message,String dirPath,String fileName, int scale) throws UnsupportedEncodingException{
		File makeDir = new File(dirPath);
		if(!makeDir.exists()){
			makeDir.mkdir();
		}

		Qrcode qrcode = new Qrcode();
		qrcode.setQrcodeErrorCorrect('M');
		qrcode.setQrcodeEncodeMode('B');
		qrcode.setQrcodeVersion(0); //auto version selected!
		if(scale==0) scale = 3;
		int image_size = scale*30+2;
		BufferedImage bi = new BufferedImage(image_size, image_size, BufferedImage.TYPE_INT_BGR);
		Graphics2D g = bi.createGraphics();
		g.setBackground(Color.WHITE);
		g.clearRect(0,0,image_size,image_size);
		g.setColor(Color.BLACK);
		byte[] d = null;
		d = message.getBytes("UTF-8"); //스캐니에서는 이걸 추천하든데...

//		if(d.length>0 && d.length<300){  //이건 빼도 될듯도 하고...
		boolean[][] b = qrcode.calQrcode(d);
		for(int i=0;i<b.length;i++){
			for(int j=0;j<b.length;j++){
				if(b[j][i]){
					g.fillRect(j*scale+2,i*scale+2,scale,scale);
				}
			}
		}
//		}
		g.dispose();
		bi.flush();
		File outFile = new File(dirPath+fileName);
		if(outFile.exists()){
			outFile.delete();
		}
		try {
			ImageIO.write(bi, "png", outFile);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return  outFile;
	}*/


	/**
	 * <strong>title</strong> : crop  <BR/>
	 * <strong>description</strong> : 이미지크기가 클경우 자른다. <BR/>
	 * <strong>date</strong> : 2011. 1. 25.
	 * @param srcFile
	 * @param destFile
	 * @param maxWidth
	 * @param xyRatio
	 * @throws IOException
	 */
	public static void crop(File srcFile,File destFile, int maxWidth, double xyRatio) throws IOException{
		BufferedImage  bufImg = getImageFromFile(srcFile);
		FileOutputStream fos = new FileOutputStream(destFile);
		fos.write(generateImage( bufImg, maxWidth, xyRatio));
		fos.close();
	}

	/**
	 * <strong>title</strong> : crop  <BR/>
	 * <strong>description</strong> : URL 이미지를 썸네일로 만든다. <BR/>
	 * <strong>date</strong> : 2011. 1. 25.
	 * @param url
	 * @param destFile
	 * @param maxWidth
	 * @param xyRatio
	 * @throws IOException
	 */
	public static void crop(String url,File destFile, int maxWidth, double xyRatio) throws IOException{
		BufferedImage  bufImg = getImageFromUrl(url);
		FileOutputStream fos = new FileOutputStream(destFile);
		fos.write(generateImage( bufImg, maxWidth, xyRatio));
		fos.close();
	}


	/**
	 * <strong>title</strong> : getImageContent  <BR/>
	 * <strong>description</strong> : URL이미지를 byte로 가지고 온다. <BR/>
	 * <strong>date</strong> : 2011. 1. 25.
	 * @param url
	 * @return
	 * @throws IOException
	 */
	private static BufferedImage getImageFromUrl(String imgUrl) throws IOException {
		URL url = new URL(imgUrl);
        ByteArrayOutputStream bais = new ByteArrayOutputStream();
        InputStream is = null;
        is = url.openStream ();
        byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
        int n;
        while ( (n = is.read(byteChunk)) > 0 ) {
        	bais.write(byteChunk, 0, n);
        }
        is.close();
        BufferedImage originalImg = ImageIO.read( new ByteArrayInputStream(bais.toByteArray()));
        return originalImg;
    }

	private static BufferedImage getImageFromFile(File file) throws IOException{
		BufferedImage originalImg = ImageIO.read(file);
		return originalImg;
	}


	private static byte[] generateImage( BufferedImage image, int maxWidth, double xyRatio) throws IOException {
		BufferedImage originalImg = image;
        //get the center point for crop
        int[] centerPoint = { originalImg.getWidth() /2, originalImg.getHeight() / 2 };
        //calculate crop area
        int cropWidth=originalImg.getWidth();
        int cropHeight=originalImg.getHeight();
        if( cropHeight > cropWidth * xyRatio ) {
            //long image
            cropHeight = (int) (cropWidth * xyRatio);
        } else {
            //wide image
            cropWidth = (int) ( cropHeight / xyRatio) ;
        }
        //set target image size
        int targetWidth = cropWidth;
        int targetHeight = cropHeight;
        if( targetWidth > maxWidth) {
            //too big image
            targetWidth = maxWidth;
            targetHeight = (int) (targetWidth * xyRatio);
        }
        //processing image
        BufferedImage targetImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = targetImage.createGraphics();
        graphics2D.setBackground(Color.WHITE);
        graphics2D.setPaint(Color.WHITE);
        graphics2D.fillRect(0, 0, targetWidth, targetHeight);
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.drawImage(originalImg, 0, 0, targetWidth, targetHeight,   centerPoint[0] - (cropWidth /2) , centerPoint[1] - (cropHeight /2), centerPoint[0] + (cropWidth /2), centerPoint[1] + (cropHeight /2), null);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        ImageIO.write(targetImage, "png", output);
        return output.toByteArray();
    }

}